#include "tactics.h"

uint8_t lastchessboard[9];
uint8_t chessboard[9];
uint8_t lookchessboard[9];
//uint8_t savechessboard[9];
uint8_t opencvchessboard[9];

uint8_t FoulWarning = 0;

uint8_t save_num;

float copy_angle;

/**
 * @brief  
 * @param  
 * @retval 无
 */
void update_angle(void)
{
	copy_angle = (angle_arror - angle_init);
			
	if(copy_angle > 45.0f) {
		copy_angle -= 90.0f;
	} 
	if(copy_angle < -45.0f) {
		copy_angle += 90.0f;
	}
	
	copy_angle = (copy_angle / 180.f) * PI;
}

#define _2PI 6.28318530718f
uint8_t xz_flag = 0;
uint8_t user_xz_flag = 0;
/**
 * @brief  
 * @param  
 * @retval 无
 */
void motor_update_angle(void)
{
	copy_angle = (CAN_Motor_getTotalAngle(CAN_Motor_ID4) / 8192.0f) * _2PI;
	if (-90.0f < copy_angle && copy_angle < 90.0f) {
		xz_flag = 0;
	} else {
		xz_flag = 1;
	}
}

void cpy_angle(void)
{
	if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10) == GPIO_PIN_RESET) {
		if (fun_key_get(0)) {
			update_angle();
			buzz_didi(4);
		}
		user_xz_flag = 0;
	} else {
		motor_update_angle();
		user_xz_flag = 1;
		//update_angle();
	}
	
//	if (FoulWarning == 1) {
//		for (uint8_t i=0; i < 8; i++) {
//			led_not(i, 0xff0000);
//		}
//	}
}

float get_angle(void)
{
	return copy_angle;
}

/**
 * @brief  判断单颗子赢得状态
 * @param  
 * @retval 无
 */
uint8_t isVictory_sign(uint8_t *chb, uint8_t num)
{
	for (uint8_t i=0; i < 3; i++) {
		
		/* 竖着连在一起 */
		if (chb[i] == num && chb[i+3] == num && chb[i+6] == num) {
			return 1;
		}
		
		/* 横着连在一起 */
		if (chb[3*i] == num && chb[3*i+1] == num && chb[3*i+2] == num) { 
			return 1;
		}
	}
	
	/* 斜着 */
	if (chb[4] == num) {	//中间得有
		if (chb[0] == num && chb[8] == num) {
			return 1;
		}
		
		if (chb[2] == num && chb[6] == num) {
			return 1;
		}
	}
		
	return 0;
}

/**
 * @brief  判断输赢
 * @param  
 * @retval 无
 */
uint8_t isVictory(uint8_t *chb, uint8_t mycolor)
{
	/* 我有没有赢 */
	if (isVictory_sign(chb, mycolor)) {
		return 1;
	}
	
	uint8_t you = (mycolor == user_bl) ? user_wr : user_bl;
	
	/* 白棋有没有赢 */
	if (isVictory_sign(chb, you)) {
		return 2;
	}
	
	return 0;
}

/**
 * @brief  复制状态
 * @param  
 * @retval 无
 */
void chess_cpy(uint8_t *to, uint8_t *in)
{
	for (char i=0; i < 9; i++) {
		to[i] = in[i];
		//savechessboard[i] = n[i];
	}
}

///**
// * @brief  保存当前棋子状态
// * @param  
// * @retval 无
// */
//void save_now_state(uint8_t *n)
//{
//	for (char i=0; i < 9; i++) {
//		chess_cpy(savechessboard, n);
//		//savechessboard[i] = n[i];
//	}
//}

/**
 * @brief  获取有几处不同
 * @param  
 * @retval 无
 */
uint8_t chack_board_state(uint8_t *n, uint8_t *n1)
{
	uint8_t num = 0;
	for (char i=0; i < 9; i++) {
		if (n1[i] != n[i]) {
			num++;
		}
	}
	
	return num;
}

/**
 * @brief  判断两个棋盘长度
 * @param  
 * @retval 无
 */
int8_t get_chass_len(uint8_t *u1, uint8_t *u2)
{
	uint8_t u1len=0, u2len=0;
	
	for (char i=0; i < 9; i++) {

		if (u1[i] == 0) {
			u1len++;
		}
		
		if (u2[i] == 0) {
			u2len++;
		}
	}
	
	if (u1len > u2len) {
		return 1;
	} else if (u1len == u2len) {
		return 0;
	} else {
		return -1;
	}
}

/**
 * @brief  检查保存的和输入的是否有差别
 * @param  
 * @retval 无
 */
uint8_t chack_board_state_abs(uint8_t *n1, uint8_t *n2)
{
	if (get_chass_len(n1, n2) == -1) {
		return 0;
	}
	
	return chack_board_state(n1, n2);
}

/**
 * @brief  判断连子
 * @param  
 * @retval 无
 */
char isOpportunity(uint8_t *chb, uint8_t my)
{
	
	for (uint8_t i=0; i < 3; i++) {
		
		/* 竖着连在一起 */
		if (chb[i] == my && chb[i+3] == my && chb[i+6] == 0) {
			return i+6;
		}
		if (chb[i] == my && chb[i+3] == 0 && chb[i+6] == my) {
			return i+3;
		}
		if (chb[i] == 0 && chb[i+3] == my && chb[i+6] == my) {
			return i;
		}
		
		/* 横着连在一起 */
		if (chb[3*i] == my && chb[3*i+1] == my && chb[3*i+2] == 0) {
			return (3*i)+2;
		}
		if (chb[3*i] == my && chb[3*i+1] == 0 && chb[3*i+2] == my) {
			return (3*i)+1;
		}
		if (chb[3*i] == 0 && chb[3*i+1] == my && chb[3*i+2] == my) {
			return 3*i;
		}
	}
	
	/* 斜着 */
	if (chb[0] == my && chb[4] == my && chb[8] == 0) {
		return 8;
	}
	
	if (chb[0] == my && chb[4] == 0 && chb[8] == my) {
		return 4;
	}
	if (chb[0] == 0 && chb[4] == my && chb[8] == my) {
		return 0;
	}
	
	
	if (chb[2] == my && chb[4] == my && chb[6] == 0) {
		return 6;
	}
	if (chb[2] == my && chb[4] == 0 && chb[6] == my) {
		return 4;
	}
	if (chb[2] == 0 && chb[4] == my && chb[6] == my) {
		return 2;
	}
	
	//写错了，只能用-1应付一下了
	return -1;
}

/**
 * @brief  会赢？
 * @param  
 * @retval 无
 */
uint8_t isWin(uint8_t *chb, uint8_t my)
{
	return isOpportunity(chb, my) + 1;
}

/**
 * @brief  会输？
 * @param  
 * @retval 无
 */
uint8_t isTransport(uint8_t *chb, uint8_t my)
{
	if (my == 1) {	//我是小黑子，我看看白子有没有赢的办法，有就堵死
		my = 2;
	} else {
		my = 1;
	}
	return isOpportunity(chb, my) + 1;
}

/**
 * @brief  返回下了几颗琪
 * @param  
 * @retval 无
 */
uint8_t get_chess_num_max(uint8_t *chess)
{
	 uint8_t max = 0;
	for (uint8_t num = 0; num < 9; num++) {
		if (chess[num] != 0) {
			max++;
		}
	}	
	
	return max;
}



/**
 * @brief  会输？
 * @param  
 * @retval 无
 */
uint8_t isIndeterminacy(uint8_t *chb, uint8_t my)
{
	if (chb[7] != my && chb[7] != 0 && chb[3] != my && chb[3] != 0 && chb[4] == 0) {
		return 4;
	}
	
	if (chb[7] != my && chb[7] != 0 && chb[5] != my && chb[5] != 0 && chb[4] == 0) {
		return 4;
	}
	
	if (chb[3] != my && chb[3] != 0 && chb[1] != my && chb[1] != 0 && chb[4] == 0) {
		return 4;;
	}
	
	if (chb[1] != my && chb[1] != 0 && chb[5] != my && chb[5] != 0 && chb[4] == 0) {
		return 4;
	}
	
	if (chb[1] != my && chb[1] != 0 && chb[0] == 0) {
		return 0;
	}
	
	if (chb[3] != my && chb[3] != 0 && chb[0] == 0) {
		return 0;
	}
	
	if (chb[5] != my && chb[5] != 0 && chb[2] == 0) {
		return 2;
	}
	
	if (chb[7] != my && chb[7] != 0 && chb[6] == 0) {
		return 6;
	}

//	if (cnt >= 2 && chb[4] == 0) {
//		return 4;
//	}
//	if (chb[3] != my && chb[3] != 0 && chb[7] != my && chb[7] != 0 && chb[6] == 0) {
//		return 7;
//	}
//	
//	if (chb[7] != my && chb[7] != 0 && chb[5] != my && chb[5] != 0 && chb[8] == 0) {
//		return 9;
//	}
	
	if (chb[4] == 0 && (chb[0] != 0 || chb[2] != 0 || chb[6] != 0 || chb[8] != 0) \
									&& (chb[0] != my || chb[2] != my || chb[6] != my || chb[8] != my)) {
		return 4;
	}
									
	//陈川bug算法
	if (chb[1] == my && chb[3] == my && chb[0] == 0) {
		return 0;
	}
	if (chb[1] == my && chb[5] == my && chb[2] == 0) {
		return 2;
	}
	if (chb[3] == my && chb[7] == my && chb[6] == 0) {
		return 6;
	}
	if (chb[7] == my && chb[4] == my && chb[8] == 0) {
		return 8;
	}
	
	//必胜
	if (chb[4] == my) {
		if (chb[0] == my) {
			if (chb[1] == 0 && (chb[3] != 0 && chb[3] != my)) {
				return 1;
			}
			
			if (chb[3] == 0 && (chb[1] != 0 && chb[1] != my)) {
				return 3;
			}
		}
		
		if (chb[2] == my) {
			if (chb[1] == 0 && (chb[5] != 0 && chb[5] != my)) {
				return 1;
			}
			if (chb[5] == 0 && (chb[1] != 0 && chb[1] != my)) {
				return 5;
			}
		}
		
		if (chb[6] == my) {
			if (chb[3] == 0 && (chb[7] != 0 && chb[7] != my)) {
				return 3;
			}
			
			if (chb[7] == 0 && (chb[3] != 0 && chb[3] != my)) {
				return 7;
			}
		}
		
		if (chb[8] == my) {
			if (chb[7] == 0 && (chb[5] != 0 && chb[5] != my)) {
				return 7;
			}
			
			if (chb[5] == 0 && (chb[7] != 0 && chb[7] != my)) {
				return 5;
			}
		}
	}
	
	/* 第二部有bug，下1位置 */
	if ( get_chess_num_max(chb) == 3) {
		if ( chb[4] == my && (chb[0] != 0 || chb[2] != 0 || chb[6] != 0 || chb[8] != 0) \
											&& (chb[0] != my || chb[2] != my || chb[6] != my || chb[8] != my) ) {
			return 1;
		}
	}
							
	for (uint8_t i=0; i < 5; i++) {
		if (chb[i*2] == 0) {
			return i*2;
		}
	}
	
	for (uint8_t i=0; i < 4; i++) {
		if (chb[i*2+1] == 0) {
			return i*2+1;
		}
	}
	
	return 0;
}

/**
 * @brief  获取下哪颗比较好
 * @param  
 * @retval 无
 */
uint8_t get_black_num(uint8_t *chb, uint8_t my)
{
	uint8_t num = 0;
	
	num = isWin(chb, my);
	if (num) {
		return num-1;
	}
	
	num = isTransport(chb, my);
	if (num) {
		return num-1;
	}
	
	num = isIndeterminacy(chb, my);
	
	return num;
}

/**
 * @brief  清除状态
 * @param  
 * @retval 无
 */
void clern_chess(uint8_t *u)
{
	for (uint8_t i=0; i < 9; i++) {
		u[i] = 0;
	}
}

/**
 * @brief  改棋子
 * @param  
 * @retval 无
 */
void change_chess_zi(uint8_t *new_c, uint8_t *last_c)
{	
	uint8_t cnt[2] = {0,0};
	uint8_t pos[2];

	for (uint8_t i=0; i < 9; i++) {
		if (new_c[i] != 0 && last_c[i] == 0) {
			cnt[0]++;
			pos[0] = i;
		}
	}
	
	for (uint8_t i=0; i < 9; i++) {
		if (new_c[i] == 0 && last_c[i] != 0) {
			cnt[1]++;
			pos[1] = i;
		}
	}
	
	if (cnt[1] == 1 && cnt[0] == 1 && pos[1] != pos[0]) {
		change_piece(pos[0], pos[1]);
	}
}

/**
 * @brief  棋盘移动规划
 * @param  
 * @retval 无
 */
void ChessboardMovePlanning(uint8_t *Old, uint8_t *New, uint8_t no_same)
{
	WS_Clear(0xff00ff);
	if (no_same == 2) {	//两个地方不同
		change_chess_zi(New, Old);
	}
	
	WS_Clear(0);
	vTaskDelay(3000);
//	chess_cpy(New, Old);
}

uint8_t error_num;
/**
 * @brief  获取视觉说哪个棋下了
 * @param  
 * @retval 无
 */
int8_t tactics_key_get_num(uint8_t my)
{
	error_num = chack_board_state_abs(chessboard, lookchessboard);
	
	//建议加上临界区
	if (error_num == 1) {	//有1个地方不同
		uint8_t who_num = 0;
		
		for (uint8_t i=0; i < 9; i++) {
			
			//检测用户有没有下棋
			if (lookchessboard[i] == my  && chessboard[i] == 0) {
				return i;
			}
		}
		
		for (uint8_t i=0; i < 9; i++) {
			if (lookchessboard[i] != my && lookchessboard[i] != 0  && chessboard[i] == 0) {
				
				//多下的给他放回去
				if (my == user_wr) {
					replayChess(chess_zi_num_max - chess_zi_residue_wr+1, i);
					go_home();
				} else {
					replayChess(chess_zi_num_max - chess_zi_residue_bl+1, i);
					go_home();
				}
				
				vTaskDelay(3000);
				return -1;
			}
		}
		
		//检测评委有没有在第0颗棋子给我动手脚
		
	}
	
	
	if (error_num >= 2	/* 看看有没有人改动棋子 */) {
		ChessboardMovePlanning(chessboard, lookchessboard, error_num);
		return -1;
	}
	
	return -1;
}

/**
 * @brief  判断平局
 * @param  
 * @retval 无
 */
uint8_t isDraw(uint8_t *u)
{
	uint8_t cnt=0;
	
	for (uint8_t i=0; i < 9; i++) {
		if (u[i] != 0) {
			cnt++;
		}
	}
	
	if (cnt == 9) {
		return 1;
	}
	
	return 0;
}
/******************* (C) COPYRIGHT 2022 FUYEBING*****END OF FILE************/
